#include "stdafx.h"
#include <XDraw.h>



std::vector<XWindow*>* windowQueue;
std::vector<XRenderPack*>* renderQueue;
std::vector<XTextPack*>* textQueue;

void XDrawModule::Initialize()
{
	glutDisplayFunc(_render);
	windowQueue = &WindowQueue;
	renderQueue = &RenderQueue;
	textQueue = &TextQueue;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, 1280, 720, 0, 1, -1);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glDisable(GL_DEPTH_TEST);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glClearColor(0, 0, 0, 1);

	ilInit();
	ilClearColor(255, 255, 255, 0);

	glewInit();
}

void XDrawModule::PreUpdate()
{

}

void XDrawModule::PostUpdate()
{
	_render();
}

void XDrawModule::Exit()
{

}

XDrawModule::XDrawModule()
{

}

void XDrawModule::RegisterWindow(XWindow* window)
{
	WindowQueue.push_back(window);
}

void XDrawModule::UnregisterWindow(XHash hash)
{
	for(int i=0; i<WindowQueue.size(); i++)
	{
		if(WindowQueue[i]->Hash == hash)
		{
			WindowQueue.erase(WindowQueue.begin() + i);
			break;
		}
	}
}

XRenderPack* XDrawModule::AddRenderPack(const char* name)
{
	XRenderPack* ren = new XRenderPack(XHash(name));
	RenderQueue.push_back(ren);

	return ren;
}

XRenderPack* XDrawModule::AddRenderPack(XHash hash)
{
	XRenderPack* ren = new XRenderPack(hash);
	RenderQueue.push_back(ren);

	return ren;
}

XRenderPack* XDrawModule::GetRenderPack(XHash hash)
{
	for(int i=0; i<RenderQueue.size(); i++)
	{
		if(RenderQueue[i]->GetHash() == hash)
			return RenderQueue[i];
	}

	return NULL;
}

XRenderPack* XDrawModule::GetRenderPack(const char* name)
{
	for(int i=0; i<RenderQueue.size(); i++)
	{
		if(RenderQueue[i]->GetHash() == name)
			return RenderQueue[i];
	}

	return NULL;
}

void XDrawModule::DeleteRenderPack(XHash hash)
{
	for(int i=0; i<RenderQueue.size(); i++)
	{
		if(RenderQueue[i]->GetHash() == hash)
		{
			RenderQueue.erase(RenderQueue.begin() + i);
			break;
		}
	}
}

void XDrawModule::DeleteRenderPack(const char* name)
{
	for(int i=0; i<RenderQueue.size(); i++)
	{
		if(RenderQueue[i]->GetHash() == name)
		{
			RenderQueue.erase(RenderQueue.begin() + i);
			break;
		}
	}
}

XTextPack* XDrawModule::AddTextPack(const char* name)
{
	XTextPack* ren = new XTextPack(XHash(name));
	TextQueue.push_back(ren);

	return ren;
}

XTextPack* XDrawModule::AddTextPack(XHash hash)
{
	XTextPack* ren = new XTextPack(hash);
	TextQueue.push_back(ren);

	return ren;
}

XTextPack* XDrawModule::GetTextPack(XHash hash)
{
	for(int i=0; i<TextQueue.size(); i++)
	{
		if(TextQueue[i]->GetHash() == hash)
			return TextQueue[i];
	}

	return NULL;
}

XTextPack* XDrawModule::GetTextPack(const char* name)
{
	for(int i=0; i<TextQueue.size(); i++)
	{
		if(TextQueue[i]->GetHash() == name)
			return TextQueue[i];
	}

	return NULL;
}

void XDrawModule::DeleteTextPack(XHash hash)
{
	for(int i=0; i<TextQueue.size(); i++)
	{
		if(TextQueue[i]->GetHash() == hash)
		{
			TextQueue.erase(TextQueue.begin() + i);
			break;
		}
	}
}

void XDrawModule::DeleteTextPack(const char* name)
{
	for(int i=0; i<TextQueue.size(); i++)
	{
		if(TextQueue[i]->GetHash() == name)
		{
			TextQueue.erase(TextQueue.begin() + i);
			break;
		}
	}
}

void XDrawModule::_render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	for(int i=0; i<renderQueue->size(); i++)
	{
		_renderXRenderPack((*renderQueue)[i]);
	}

	for(int i=0; i<textQueue->size(); i++)
	{
		_renderXTextPack((*textQueue)[i]);
	}

	for(int i=0; i<windowQueue->size(); i++)
	{
		XWindow* win = (*windowQueue)[i];

		_renderXRenderPack(win->WindowLayout);
		_renderXTextPack(win->WindowTitle);

		for(int j=0; j<win->ControlsRender.size(); j++)
		{
			_renderXRenderPack(win->ControlsRender[j]);
			
		}

		for(int j=0; j<win->ControlsText.size(); j++)
		{
			_renderXTextPack(win->ControlsText[j]);
		}
	}

	glutSwapBuffers();
}

void XDrawModule::_renderXRenderPack(XRenderPack* renderpck)
{
	glPushMatrix();

	glColor4f((float)renderpck->GetColor().R/255, (float)renderpck->GetColor().G/255, (float)renderpck->GetColor().B/255, (float)renderpck->GetColor().A/255);

	if(renderpck->GetTranslation().X != 0 || renderpck->GetTranslation().Y != 0)
		glTranslatef(renderpck->GetTranslation().X, renderpck->GetTranslation().Y, 0);
	if(renderpck->GetScale() != 1)
		glScalef(renderpck->GetScale(), renderpck->GetScale(), 1);
	if(renderpck->GetRotation() != 0)
		glRotatef(renderpck->GetRotation(), 0, 0, 1);

	if(renderpck->Texture != NULL && renderpck->Vertex.size() != 0)
	{
		glBindTexture(GL_TEXTURE_2D, renderpck->Texture->ID);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER, renderpck->VertexBuffer);

		glTexCoordPointer(2, GL_FLOAT, sizeof(XVertexData), (void*) offsetof(XVertexData, TextureCoord));
		glVertexPointer(2, GL_FLOAT, sizeof(XVertexData), (void*) offsetof(XVertexData, Position));

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderpck->IndexBuffer);
		glDrawElements(GL_TRIANGLE_STRIP, renderpck->Vertices, GL_UNSIGNED_INT, NULL);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D, NULL);
		glBindBuffer(GL_ARRAY_BUFFER, NULL);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
	}
	else if(renderpck->Vertex.size() != 0)
	{
		glBindBuffer(GL_ARRAY_BUFFER, renderpck->VertexBuffer);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderpck->IndexBuffer);

		glEnableClientState(GL_VERTEX_ARRAY);

		glVertexPointer(2, GL_FLOAT, 0, NULL);
		if(renderpck->LineMode)
			glDrawElements(GL_LINE_STRIP, renderpck->Vertices, GL_UNSIGNED_INT, NULL);
		else
			glDrawElements(GL_TRIANGLE_STRIP, renderpck->Vertices, GL_UNSIGNED_INT, NULL);

		glDisableClientState(GL_VERTEX_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER, NULL);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
	}

	glPopMatrix();
}

void XDrawModule::_renderXTextPack(XTextPack* textpck)
{
	glPushMatrix();

	glColor4f((float)textpck->GetColor().R/255, (float)textpck->GetColor().G/255, (float)textpck->GetColor().B/255, (float)textpck->GetColor().A/255);

	if(textpck->GetTranslation().X != 0 || textpck->GetTranslation().Y != 0)
		glTranslatef(textpck->GetTranslation().X, textpck->GetTranslation().Y, 0);
	if(textpck->GetScale() != 1)
		glScalef(textpck->GetScale(), textpck->GetScale(), 1);
	if(textpck->GetRotation() != 0)
		glRotatef(textpck->GetRotation(), 0, 0, 1);

	if(textpck->GetText().length() != 0 && textpck->Font != NULL)
	{
		float dX = textpck->TextBox.X;
		float dY = textpck->TextBox.Y;

		glBindTexture(GL_TEXTURE_2D, textpck->Font->ID);
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER, textpck->Font->VertexBuffer);

		glTexCoordPointer(2, GL_FLOAT, sizeof(XVertexData), (void*) offsetof(XVertexData, TextureCoord));
		glVertexPointer(2, GL_FLOAT, sizeof(XVertexData), (void*) offsetof(XVertexData, Position));

		for( int i = 0; i < textpck->Text.length(); ++i )
		{
			if( textpck->Text[ i ] == ' ')
			{
				dX += textpck->Font->Space;
			}

			else if(textpck->Text[ i ] == '\n')
			{
				if(dY-textpck->TextBox.Y + textpck->Font->NewLine < textpck->TextBox.H || textpck->TextBox.H == 0)
				{
					dY += textpck->Font->NewLine;
					dX = textpck->TextBox.X;
				}
			}

			else if(dX-textpck->TextBox.X + textpck->Font->Clips[(unsigned char)textpck->Text[i]].W < textpck->TextBox.W || textpck->TextBox.W == 0)
			{
				unsigned int ascii = (unsigned char)textpck->Text[i];

				glPushMatrix();
				glTranslatef(dX, dY, 0);

				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, textpck->Font->IndexBuffer[ascii]);
				glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, NULL);

				dX += textpck->Font->Clips[ascii].W+1;

				glPopMatrix();
			}
		}

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D, NULL);
		glBindBuffer(GL_ARRAY_BUFFER, NULL);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
	}

	glPopMatrix();
}